package com.such.kitx.tax;

import java.util.List;
import java.util.Map;
import com.such.kit.io.template.XmlIOTemplate;

/**
 * @author SUCH
 * <pre>
 * 税控接口
 * 设计初衷在于统一各个厂商的税控服务接口，提供统一的原始接口
 * 此接口的定位是不包含业务流程、尽量使用通用、原始的入参、返回值
 * 由于各个厂商的税控服务接口实现差异较大，TaxInterface 中的方法会对税控服务接口中类似的功能、方法进行整合，并在具体的实现类中补充说明信息
 * 
 * 由于厂商在各地使用的接口存在差异，导致税控服务接口版本众多，处理各版本的兼容性也是 TaxInterface 重点任务
 * 接口差异最终会反应到 xml 的个格式差异，因此通过多版本的 xml 模板管理来实现多版本兼容，同时使用 {@link XmlIOTemplate} 来处理基于 xml 模板的 xml 生成、解析
 * 关于版本管理我们做如下约定
 * 1. 版本字符串构成 V[继承版本][版本编号]
 *      [版本编号] 为 4 位数字，从 0001 开始，每次版本更新 +1
 *      [继承版本] 为 4 位数字，从 0000 开始，0000 表示为 root，再无上级版本
 *      [举例]
 *      V00000001 [主版本]
 *      V00010002 [第 1 次版本更新，版本编号 +1 为 0002，继承自 V00000001，继承版本为 0001]
 *      V00020003 [第 2 次版本更新，版本编号 +1 为 0003，继承自 V00010002，继承版本为 0002]
 *      V00030004 [第 3 次版本更新，并进行了第 1 次分支拆分，版本编号 +1 为 0004，继承自 V00030004，继承版本为 0003]
 *      V00030005 [拆分出的新分支，版本编号 +1 为 0005，继承自 V00020003，继承版本为 0003]
 *      V00000006 [新的主版本，此版本与 V00000001 及取分支已无继承关系]
 * 2. 在指定文件夹下按版本创建文件夹，存放对应版本的 xml 模板，xml 模板可以做增量更新
 * 3. 当在版本中的未找到指定模板时，将向上到 [继承版本] 中查找，直到找到模板或者找到 root
 * 
 * 各厂商的接口入参、返回值都采用 xml 形式的报文结构，TaxInterface 的实现类需要生成、解析 xml，而数据载体的形式为 Map<String, Object>
 * 关于 Map<String, Object> 我们做如下约定
 * 1. 简单的数据类型统一为 String
 * 2. 对象的数据类型统一为 Map<String, Object>
 * 3. 集合的数据类型统一为 List<Map<String, Object>>
 * 这样可以简化实现类的数据处理逻辑
 * 
 * 为了方便开发人员快速的填充、获取数据，xml 模板可以有对应的数据模板
 * 在数据模板中预制了对数据的 put、get 方法以及字段说明，通过 {@link TaxHelper#printDataTemplate(String, String, String, String)} 方法可以将模板输出到控制台
 * </pre>
 */
public interface TaxInterface {

	/** TEMPLATE_BASIC_PATH：模板文件根目录 */
	public static final String TEMPLATE_ROOT_PATH = "com/such/kitx/tax/template";
	/** DATA_TEMPLATE_SUFFIX：数据模板扩充后缀，数据模板后缀名默认为 .xmld，既在 .xml 的基础上扩充了 d */
	public static final String DATA_TEMPLATE_SUFFIX = "d";
	/** TAX_VENDOR_AISINO：税控服务厂商，航信 */
	public static final String TAX_VENDOR_AISINO = "aisino";
	/** TAX_VENDOR_BAIWANG：税控服务厂商，百旺 */
	public static final String TAX_VENDOR_BAIWANG = "baiwang";

	/**
	 * <pre>
	 * 开具发票
	 * 
	 * 入参为请求参数集，如果厂商的税控服务接口支持批量处理，应该优先基于批量接口实现
	 * 
	 * [业务补充]
	 * 1. 目前需要支持 5 类发票的开具
	 *      {@link #FPLX_ZZP 增值税专用发票}
	 *      {@link #FPLX_ZPP 增值税普通发票}
	 *      {@link #FPLX_ZDPP 增值税电子普通发票}
	 *      {@link #FPLX_YSYZZP 货物运输业增值税专用发票}
	 *      {@link #FPLX_JDCXTP 机动车销售统一发票}
	 *    各类发票所要求的请求报文不尽相同，需要分类处理
	 * 2. 红冲开具也是调用此方法
	 * 3. 部分种类的发票可以进行有清单开具
	 * </pre>
	 * @param paramsArray 请求参数集
	 * @return 反馈结果集
	 * @throws Exception
	 */
	public List<Map<String, Object>> KJFP(Map<String, Object>... paramsArray) throws Exception;

	/**
	 * <pre>
	 * 打印设置
	 * 
	 * 入参为请求参数集，如果厂商的税控服务接口支持批量处理，应该优先基于批量接口实现
	 * </pre>
	 * @param paramsArray 请求参数集
	 * @return 反馈结果集
	 * @throws Exception
	 */
	public List<Map<String, Object>> DYSZ(Map<String, Object>... paramsArray) throws Exception;

	/**
	 * <pre>
	 * 打印发票
	 * 
	 * 入参为请求参数集，如果厂商的税控服务接口支持批量处理，应该优先基于批量接口实现
	 * 
	 * [业务补充]
	 * 1. 部分种类的发票可以进行清单打印
	 * </pre>
	 * @param paramsArray 请求参数集
	 * @return 反馈结果集
	 * @throws Exception
	 */
	public List<Map<String, Object>> DYFP(Map<String, Object>... paramsArray) throws Exception;

	/**
	 * <pre>
	 * 作废发票
	 * 
	 * 入参为请求参数集，如果厂商的税控服务接口支持批量处理，应该优先基于批量接口实现
	 * 
	 * [业务补充]
	 * 1. 作废分为空白发票作废、已开发票作废
	 * </pre>
	 * @param paramsArray 请求参数集
	 * @return 反馈结果集
	 * @throws Exception
	 */
	public List<Map<String, Object>> ZFFP(Map<String, Object>... paramsArray) throws Exception;

	/**
	 * <pre>
	 * 发票上传
	 * 将发票开具信息实时上传到税务系统
	 * 
	 * 入参为请求参数集，如果厂商的税控服务接口支持批量处理，应该优先基于批量接口实现
	 * </pre>
	 * @param paramsArray 请求参数集
	 * @return 反馈结果集
	 * @throws Exception
	 */
	public List<Map<String, Object>> FPSC(Map<String, Object>... paramsArray) throws Exception;

	/**
	 * <pre>
	 * 发票更新
	 * 检查税务系统是否完成发票开具信息的记录，并将其相关状态返回
	 * 
	 * 入参为请求参数集，如果厂商的税控服务接口支持批量处理，应该优先基于批量接口实现
	 * </pre>
	 * @param paramsArray 请求参数集
	 * @return 反馈结果集
	 * @throws Exception
	 */
	public List<Map<String, Object>> FPGX(Map<String, Object>... paramsArray) throws Exception;

	/**
	 * <pre>
	 * 上传红字
	 * 进行红冲前需要红冲申请
	 * 1. 填写红字信息表
	 * 2. 上传红字信息表
	 * 3. 等待反馈信息
	 * 
	 * 入参为请求参数集，如果厂商的税控服务接口支持批量处理，应该优先基于批量接口实现
	 * </pre>
	 * @param paramsArray 请求参数集
	 * @return 反馈结果集
	 * @throws Exception
	 */
	public List<Map<String, Object>> SCHZ(Map<String, Object>... paramsArray) throws Exception;

	/**
	 * <pre>
	 * 抄报
	 * 
	 * 入参为请求参数集，如果厂商的税控服务接口支持批量处理，应该优先基于批量接口实现
	 * </pre>
	 * @param paramsArray 请求参数集
	 * @return 反馈结果集
	 * @throws Exception
	 */
	public List<Map<String, Object>> CB(Map<String, Object>... paramsArray) throws Exception;

	/**
	 * <pre>
	 * 清卡
	 * 
	 * 入参为请求参数集，如果厂商的税控服务接口支持批量处理，应该优先基于批量接口实现
	 * </pre>
	 * @param paramsArray 请求参数集
	 * @return 反馈结果集
	 * @throws Exception
	 */
	public List<Map<String, Object>> QK(Map<String, Object>... paramsArray) throws Exception;

	/**
	 * <pre>
	 * 输出所有数据模板中的预制内容到控制台 [参考 {@link TaxHelper#printDataTemplate(String, String, String, Map)}]
	 * </pre>
	 * @param params 参数集
	 * @throws Exception
	 */
	public void printDataTemplate(Map<String, String> params) throws Exception;

	/**
	 * <pre>
	 * 输出与指定方法相关的数据模板中的预制内容到控制台 [参考 {@link TaxHelper#printDataTemplate(String, String, String, Map)}]
	 * </pre>
	 * @param methodName 方法名
	 * @param params 参数集
	 * @throws Exception
	 */
	public void printDataTemplate(String methodName, Map<String, String> params) throws Exception;

}
